<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>this的理解进阶</title>
</head>

<body>
    <script>

        // function baz() {
        //     console.log("baz");
        //     bar(); // <-- bar 的调用位置
        // }

        // function bar() {
        //     // 当前调用栈是 baz -> bar
        //     // 因此，当前调用位置在 baz 中
        //     console.log("bar");
        //     foo(); // <-- foo 的调用位置
        // }

        // function foo() {
        //     // 当前调用栈是 baz -> bar -> foo // 因此，当前调用位置在 bar 中
        //     console.log("foo");
        // }
        // baz(); // <-- baz 的调用位置


        // function foo() {
        //     console.log(this.a);
        // }
        // var a = 2; 
        // foo(); // 2



        // function foo() {
        //     "use strict";
        //     console.log(this.a);
        // }
        // var a = 2;
        // foo(); // TypeError: this is undefined



        // function foo() {
        //     console.log(this.a);
        // }
        // var obj = {
        //     a: 2,
        //     foo: foo
        // };
        // obj.foo(); // 2


        // function foo() {
        //     console.log(this.a);
        // }
        // var obj2 = {
        //     a: 42,
        //     foo: foo
        // };
        // var obj1 = {
        //     a: 2,
        //     obj2: obj2
        // };
        // obj1.obj2.foo(); // 42



        // function foo() {
        //     console.log(this.a);
        // }
        // var obj = {
        //     a: 2,
        //     foo: foo
        // };
        // var bar = obj.foo; // 函数别名!
        // var a = "oops, global"; // a 是全局对象的属性 
        // bar(); // "oops, global"


        // function foo() {
        //     console.log(this.a);
        // }
        // function doFoo(fn) {
        //     // fn 其实引用的是 foo 
        //     fn(); // <-- 调用位置!
        // }
        // var obj = {
        //     a: 2,
        //     foo: foo
        // };
        // var a = "oops, global"; // a 是全局对象的属性 
        // doFoo( obj.foo ); // "oops, global"


        // // 显示绑定
        // function foo() {
        //     console.log(this.a);
        // }
        // var obj = {
        //     a: 2
        // };
        // foo.call(obj); // 2

        // 硬绑定
        // function foo() {
        //     console.log(this.a);
        // }
        // var obj = {
        //     a: 2
        // };
        // var bar = function () {
        //     foo.call(obj);
        // };
        // bar(); // 2
        // setTimeout(bar, 100); // 2
        // // 硬绑定的 bar 不可能再修改它的 this 
        // bar.call(window); // 2

        // function foo(something) {
        //     console.log(this.a, something); return this.a + something;
        // }
        // var obj = {
        //     a: 2
        // };
        // var bar = function () {
        //     return foo.apply(obj, arguments);
        // };
        // var b = bar(3); // 2 3 
        // console.log(b); // 5

        // new绑定
        // function foo(a) {
        //     this.a = a;
        // }
        // var bar = new foo(2);
        // console.log(bar.a); // 2

        // 绑定的优先级
        // function foo() {
        //     console.log(this.a);
        // }
        // var obj1 = {
        //     a: 2,
        //     foo: foo
        // };
        // var obj2 = {
        //     a: 3,
        //     foo: foo
        // };
        // obj1.foo(); // 2
        // obj2.foo(); // 3
        // obj1.foo.call(obj2); // 3
        // obj2.foo.call(obj1); // 2

        // function foo(something) {
        //     this.a = something;
        // }
        // var obj1 = {
        //     foo: foo
        // };
        // var obj2 = {};

        // obj1.foo(2);
        // console.log(obj1.a); // 2
        // obj1.foo.call(obj2, 3);
        // console.log(obj2.a); // 3
        // var bar = new obj1.foo(4);
        // console.log(obj1.a); // 2 
        // console.log(bar.a); // 4

        // 硬绑定
        function foo(something) {
            this.a = something;
        }
        var obj1 = {};
        var bar = foo.bind(obj1); bar(2);
        console.log(obj1.a); // 2
        var baz = new bar(3); console.log(obj1.a); // 2 
        console.log(baz.a); // 3





    </script>

</body>

</html>